import './assets/css/main.css'
import 'ol/ol.css'
import { TILEURL } from './const'
import Map from 'ol/Map'
import View from 'ol/View'
import TileLayer from 'ol/layer/Tile'
import XYZSource from 'ol/source/XYZ'
import VectorSource from 'ol/source/Vector'
import VectorLayer from 'ol/layer/Vector'
import { fromLonLat, toLonLat, transformExtent } from 'ol/proj'
import { Text, Fill, Stroke, Style } from 'ol/style'
import Feature from 'ol/Feature'
import { fromExtent } from 'ol/geom/Polygon'
import DrawTool from './tools/draw'

// 定义变量
let map
let view
let el = ''
let zoom = 2
let center = [0, 0]
let drawTool = null
let tileGridSource = null
let tileGridLayer = null

class EasyMap {
  /**
   * 初始化构造函数
   * @param {string|HTMLElement} dom - map container
   * @param {Object} options - map init options
   * @param {number} options.zoom - 初始化级别，默认为2
   * @param {Array} options.center - 初始化经纬度，默认为[0, 0]
   * @param {string} [options.tileType = 'OSM' ] - 底图参数，(顺丰)SF,OSM,(高德)NAV
   * @param {boolean} [options.isTileGrid = true] - 是否显示切片网格
   * @param {number} [options.tileGridSize = 256] - 切片网格大小
   */
  constructor (dom = 'map', options = {}) {
    options = Object.assign({
      tileType: 'OSM',
      isTileGrid: false,
      tileGridSize: 256
    }, options)
    el = dom
    zoom = options.zoom || 2
    center = fromLonLat(options.center || [0, 0])
    this.options = options
    this.initMap()
  }

  /**
   * 初始化地图
   */
  initMap () {
    view = new View({
      center: center,
      zoom: zoom
    })
    tileGridSource = new VectorSource()
    tileGridLayer = new VectorLayer({
      source: tileGridSource,
      visible: this.options.isTileGrid,
      style: feat => {
        return new Style({
          fill: new Fill({
            color: 'rgba(42,130,241,0.05)'
          }),
          stroke: new Stroke({
            color: 'rgb(255,0,0)',
            width: 1
          }),
          text: new Text({
            text: feat.get('zxy'),
            font: '14px bold',
            fill: new Fill({
              color: '#ff0000'
            }),
            stroke: new Stroke({
              color: '#fff',
              width: 3
            })
          })
        })
      }
    })
    map = new Map({
      layers: [
        new TileLayer({
          source: new XYZSource({
            url: TILEURL[this.options.tileType]
          })
        }),
        tileGridLayer
      ],
      target: el,
      view: view
    })
    const that = this
    map.on('moveend', function (e) {
      if (that.options.isTileGrid) that._getMapTileGrid()
    })
  }
  _getMapTileGrid () {
    tileGridSource.clear()
    const TILE_SIZE = this.options.tileGridSize
    const view = map.getView()
    const val0 = view.getResolutionForZoom(0) * TILE_SIZE / 2
    const originX = -val0
    const originY = val0
    const zoom = Math.ceil(view.getZoom())
    const val = view.getResolutionForZoom(zoom) * TILE_SIZE
    const [xminE, yminE, xmaxE, ymaxE] = view.calculateExtent()
    const x1 = Math.floor((xminE - originX) / val)
    const x2 = Math.ceil((xmaxE - originX) / val)
    const y2 = Math.ceil((originY - yminE) / val)
    const y1 = Math.floor((originY - ymaxE) / val)
    let getExtentFromXy = function (x, y) {
      return [
        originX + x * val,
        originY - (y + 1) * val,
        originX + (x + 1) * val,
        originY - y * val
      ]
    }

    let features = []
    for (let i = x1; i <= x2; i++) {
      for (let j = y1; j <= y2; j++) {
        const e = getExtentFromXy(i, j)
        const feature = new Feature({
          geometry: fromExtent(e),
          zxy: [zoom, i, j].join('-')
        })
        features.push(feature)
      }
    }
    tileGridSource.addFeatures(features)
  }

  /**
   *
   * @param {boolean} [visible = true] - 设置切片网格是否可见
   */
  setTileGridVisible (visible = true) {
    this.options.isTileGrid = visible
    tileGridLayer.setVisible(visible)
    if (visible) this._getMapTileGrid()
  }
  /**
   *
   * @param {boolean} [isEditTool = true] - 是否开启编辑
   * @return {DrawTool}
   */
  initDrawTool (isEditTool = true) {
    drawTool = new DrawTool(map, isEditTool)
    return drawTool
  }
  /**
   * 获取地图dom
   * @returns {HTMLElement} 地图dom
   */
  getMapElement () {
    return map.getTargetElement()
  }
  /**
   * 获取视图dom
   * @returns {HTMLElement} 视图dom
   */
  getViewElement () {
    const mapDom = this.getMapElement()
    return mapDom.querySelector('.ol-viewport')
  }
  /**
   * 获取地图画布
   * @returns {HTMLElement} 地图画布
   */
  getMapCanvas () {
    const dom = this.getViewElement()
    const layerDom = dom.querySelector('.ol-layer')
    return layerDom.querySelector('canvas')
  }
  /**
   * 设置地图中心点和缩放级别
   * @param {Array} center - center of map
   * @param {number} zoom - zoom of map
   */
  animate (center = [0, 0], zoom = 4) {
    this.zoom = zoom || this.zoom
    this.center = fromLonLat(center) || this.center
    view.animate({ zoom: this.zoom }, { center: this.center })
  }
  /**
   * 设置中心点，经纬度
   * @param {Array} center - center of map
   */
  setCenter (center) {
    this.animate(center, this.zoom)
  }
  /**
   * 设置缩放级别
   * @param {number} zoom - zoom of map
   */
  setZoom (zoom) {
    this.animate(this.center, zoom)
  }
  /**
   * 获取中心点，经纬度
   * @returns {Array} center
   */
  getCenter () {
    return toLonLat(view.getCenter())
  }
  /**
   * 返回当前级别
   * @returns {number} zoom
   */
  getZoom () {
    return view.getZoom()
  }

  /**
   * 获取当前地图返回
   * @return {array} - 返回当前地图范围，经纬度表示
   */
  getExtent () {
    return transformExtent(view.calculateExtent(), 'EPSG:3857', 'EPSG:4326')
  }
}

export default EasyMap
